Data Source Architecture Patterns
Object-Relational Behavioral Patterns
Data Source Architecture Patterns
Chapter 10,
Patterns of Enterprise Application Architecture Gateway
An object that encapsulates access to an external system or resource.

holds all the SQL for accessing a single table or view:
selects, inserts, updates, and deletes How to return the result?
The result of a query is often multiple rows, but many programming languages support only one data to be returned.
Solutions:
- Map
- Data Transfer Object
An object that carries data between processes in order to reduce the number of method calls
- Record Set
An in-memory representation of tabular data.
- or any other object corresponding to your domain model
PersonGateway
class PersonGateway...
public IDataReader FindAll() {
String sql = "select * from person";
return new OleDbCommand(sql, DB.Connection).ExecuteReader();
}
public IDataReader FindWithLastName(String lastName) {
String sql = "SELECT * FROM person WHERE lastname = ?";
IDbCommand comm = new OleDbCommand(sql, DB.Connection);
comm.Parameters.Add(new OleDbParameter("lastname", lastName));
return comm.ExecuteReader();
}
public IDataReader FindWhere(String whereClause) {
String sql = String.Format("select * from person where {0}", whereClause);
return new OleDbCommand(sql, DB.Connection).ExecuteReader();
}
Returning ...
class PersonGateway
...
public Object
[] FindRow
(long
key) {
String sql
= "SELECT * FROM person WHERE id = ?";
IDbCommand comm
= new OleDbCommand
(sql
, DB
.Connection
);
comm
.Parameters
.Add
(new OleDbParameter
("key",key));
IDataReader reader
= comm
.ExecuteReader
();
reader
.Read
();
Object
[] result
= new Object
[reader
.FieldCount
];
reader
.GetValues
(result
);
reader
.Close
();
return result
;
}
Update & Insert
public void Update
(long
key, String lastname
, String firstname
, long
numberOfDependents
){
String sql
= @"
UPDATE person
SET lastname = ?, firstname = ?, numberOfDependents = ?
WHERE id = ?";
IDbCommand comm
= new OleDbCommand
(sql
, DB
.Connection
);
comm
.Parameters
.Add
(new OleDbParameter
("last", lastname
));
comm
.Parameters
.Add
(new OleDbParameter
("first", firstname
));
comm
.Parameters
.Add
(new OleDbParameter
("numDep", numberOfDependents
));
comm
.Parameters
.Add
(new OleDbParameter
("key", key));
comm
.ExecuteNonQuery
();
}
class PersonGateway
...
public long Insert
(String lastName
, String firstName
, long numberOfDependents
) {
String sql
= "INSERT INTO person VALUES (?,?,?,?)";
long
key = GetNextID
();
IDbCommand comm
= new OleDbCommand
(sql
, DB
.Connection
);
comm
.Parameters
.Add
(new OleDbParameter
("key", key));
comm
.Parameters
.Add
(new OleDbParameter
("last", lastName
));
comm
.Parameters
.Add
(new OleDbParameter
("first", firstName
));
comm
.Parameters
.Add
(new OleDbParameter
("numDep", numberOfDependents
));
comm
.ExecuteNonQuery
();
return key;
}
one instance per row
Where to put FIND?
One idea is to have separate finder object for each table

Example
class PersonGateway...
private String lastName;
private String firstName;
private int numberOfDependents;
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public int getNumberOfDependents() {
return numberOfDependents;
}
public void setNumberOfDependents(int numberOfDependents) {
this.numberOfDependents = numberOfDependents;
}
Row Data Gateway + Domain Logic
Example
class Person...
public Money getExemption() {
Money baseExemption = Money.dollars(1500);
Money dependentExemption = Money.dollars(750);
return baseExemption.add(dependentExemption.multiply(this.getNumberOfDependents()));
}
Usually, the object schema and the relational schema don't match up
Data Mapper transfers data between the two
Example: Find

Example: Update

It can use several techniques to handle operations:
Lazy Loading, Identity Map
Metadata Mapping
Should the field names be identical in both object/data?
Where to commit changes to database?

Do load an object more than once
What key to use?
Single or Many?
Load things later!